package core

import (
	"fmt"
	"io"
	"os"
	"strings"
	"time"

	rotatelog "github.com/lestrrat/go-file-rotatelogs"
	"github.com/op/go-logging"

	"gitee.com/hwpro/cvecompetition/config"
	"gitee.com/hwpro/cvecompetition/global"
	"gitee.com/hwpro/cvecompetition/utils"
)

const (
	logDir      = "logs"
	logSoftLink = "latest_log"
	module      = "cve_competition_server"
)

var defaultFormatter = `%{time:2006/01/02 - 15:04:05.000} %{longfile} %{color:bold}▶ [%{level:.6s}] %{message}%{color:reset}`

func initLog() {
	cLog := global.GmsConfig.Log
	if cLog.Prefix == "" {
		fmt.Println("logger prefix not found")
	}
	logClient := logging.MustGetLogger(module)
	var backends [] logging.Backend
	backends = registerStdout(cLog, backends)
	backends = registerFile(cLog, backends)

	logging.SetBackend(backends...)
	global.GmsLog = logClient
}

func registerFile(log config.Log, backends []logging.Backend) []logging.Backend {
	if log.File != "" {
		if ok, _ := utils.PathExists(logDir); !ok {
			fmt.Println("create log directory")
			_ = os.Mkdir(logDir, os.ModePerm)
		}
	}
	fileWriter, err := rotatelog.New(
		logDir+string(os.PathSeparator)+"%Y-%m-%d.log",
		//Generate a soft link to point to the latest log file
		rotatelog.WithLinkName(logSoftLink),
		//Maximum time to save log files One week
		rotatelog.WithMaxAge(7*24*time.Hour),
		//Switch log files every day
		rotatelog.WithRotationTime(24*time.Hour),
	)
	if err != nil {
		fmt.Println(err)
		return backends
	}
	level, err := logging.LogLevel(log.File)
	if err != nil {
		fmt.Println(err)
	}
	backends = append(backends, createBackend(fileWriter, log, level))
	return backends
}

func registerStdout(log config.Log, backends []logging.Backend) []logging.Backend {
	if log.Stdout != "" {
		level, err := logging.LogLevel(log.Stdout)
		if err != nil {
			fmt.Println(err)
		}
		backends = append(backends, createBackend(os.Stdout, log, level))
	}

	return backends
}

func createBackend(w io.Writer, log config.Log, level logging.Level) logging.Backend {
	backend := logging.NewLogBackend(w, log.Prefix, 0)
	stoutWriter := false
	if w == os.Stdout {
		stoutWriter = true
	}
	format := getLogFormatter(log, stoutWriter)
	backendLeveled := logging.AddModuleLevel(logging.NewBackendFormatter(backend, format))
	backendLeveled.SetLevel(level, module)
	return backendLeveled
}

func getLogFormatter(c config.Log, stdoutWriter bool) logging.Formatter {
	pattern := defaultFormatter
	if !stdoutWriter {
		pattern = strings.Replace(pattern, "%{color:bold}", "", -1)
		pattern = strings.Replace(pattern, "%{color:reset}", "", -1)
	}
	if !c.LogFile {
		pattern = strings.Replace(pattern, "%{longfile}", "", -1)
	}
	return logging.MustStringFormatter(pattern)
}
